"""
pandas缺失值处理
-- 缺失值：None和np.nan
-- isnull（）
-- notnull（）
-- fillna（）
-- dropna（）
-- all（）和any（）
"""
import pandas as pd
import numpy as np

# 1有两种丢失数据（空值）
# -- None：Python中的空值，用None表示
# -- np.nan：NumPy中的空值，用np.nan表示
# 1.1 None
# -- None是python自带的，是python中得到空对象。None不能参与运算，不能参与集合运算，不能参与逻辑运算。
# -- object类型的运算要比int类型的运算慢得多
# 1.2 np.nan
# --np.nan是浮点型，能参与到计算中。但计算的结果总是Nan

# 2.pandas中None和np.nan
# 2.1pandas中None与np.nan都视为np.nan
# a. 创建DataFrame
df = pd.DataFrame(
    data=np.random.randint(0, 100, size=(5, 5)),
    index=[1, 2, 3, 4, 5],
    columns=list('ABCDE')
)
print(df)
# b. 使用DataFrame行索引与列索引修改DataFrame数据

df.loc[1, 'A'] = None

df.loc[3, 'C'] = None
df.loc[4, 'D'] = np.nan
df.loc[5, 'E'] = 100
print(df)
print(df.loc[1, 'A'], df.loc[2, 'B'], df.loc[3, 'C'], df.loc[4, 'D'])

print('\n')
# 3pandas中None和np.nan的操作
# -- 缺失值：None和np.nan
# -- isnull（）
# -- notnull（）
# -- fillna（）  ： 填充丢失数据
# -- dropna（） ： 过滤丢失数据
# -- all（）和any（）

# 3.1判断函数isnull()和notnull()
# a. isnull()：判断数据是否为None或np.nan
# b. notnull()：判断数据是否不为None或np.nan
print('\n判断函数')
print(df.isnull())
print(df.notnull())
# all()和any()
# a. all()：判断所有元素是否都为True，必须全部为True才返回True
# b. any()：判断是否存在True元素，只要有一个True，就返回True
print('\nall()和any()')
# 找有空的列
print(df.isnull().all())  # 必须全部都为空的行或列才会为True
print(df.isnull().any())  # 常用，尽可能找到有空的列或者行
# 找没有空的列
print(df.notnull().all())  # 常用，尽量找到没有空值的列或者行
print(df.notnull().any())

# 找有空的行
print(df.isnull().any(axis=1))
# 找没有空的行
print(df.notnull().any(axis=1))

# 3.2使用bool值索引过滤数据
print('\n使用bool值索引过滤数据')
cond = df.isnull().any(axis=1)  # 找出有空值的行
print(cond)  # 有一个为空，就为True，正行为True
print(~cond)  # 反之，有一个为空，就为False，正行为False
print(df[~cond])  # 过滤掉有空值的行

cond1 = df.notnull().all(axis=1)  # 找出没有空值的行
print(df[cond1])

# 过滤列
print('\n过滤列')

cond2 = df.isnull().any()
print(df.loc[:, ~cond2])
cond3 = df.notnull().all()
print(df.loc[:, cond3])


# 3.3过滤函数
# --dropna()：过滤掉所有丢失数据
print('\n过滤函数dropna()')
# 可以选着过滤的是行还是列，默认是行
print(df)
print(df.dropna())  # 默认删除有空的行
print(df.dropna(axis=1))  # 删除有空的列

# 也可以选着过滤方式how = ‘all’
print(df.dropna(how='any')) # 默认是any
print(df.dropna(how='all'))
print(df.dropna(how='all', axis=1)) # 针对列过滤

# inplace=True：直接修改原数据
df2 = df.copy()
df2.dropna(inplace=True)
print(df2)

# 3.4填充函数fillna()
# --fillna()：填充丢失数据
print('\n填充函数fillna()')
df3 = df.copy()
df3.loc[3,'D'] = np.nan
print(df3)
# print(df3.fillna(value=100))
# 限制填充的次数(从上往下填充)
print(df3.fillna(value=100, limit=1))
print(df3.fillna(value=0, limit=1,inplace=True))
print(df3)

# 可以选着向前填充还是向后填充，默认是向前填充
print('\n')
df4 = df.copy()
print(df4)
print(df4.ffill())  # 向前填充
print(df4.bfill())  # 向后填充











